//
//  MainViewController.m
//
//  Created by Hannes Kappl, Storm Christoph on 12/23/09.
//  Copyright __MyCompanyName__ 2009. All rights reserved.
//

#import "MainViewController.h"
#import "MainView.h"

#define kImageHeight		50.0
#define kImageWidth			50.0
#define kTransitionDuration	0.75

#define kTopPlacement		80.0			// y coord for the images

// parameters which are defined by user (properties menue)
int optionsNrOfCards = 16;					// nr of cards to play with
int optionsCardsToCompare = 2;				// how many cards must be compared
int optionsSecondsToRun = 60;
int optionsTypeOfCards = 0;					//0..numbers, 1..symbols, 2..pictures

// size of one card, init for 4x4 game
int cardHeight = 97;						// height of one game card
int cardWidth = 70;							// width of one game card

// max Cards per row/column, init for 4x4 game
int rowMax = 4;
int colMax = 4;

// values for the shake mechanism
double sampleRate = 10.0;
double cutoffFrequency = 5.0;
double updateInterval = (1.0 / 60.0);
int currentRoundNr = 0;

// counter for the GamePoints
int gamePoints = 0;

NSMutableArray *cardArray = nil;
NSMutableArray *positionArray = nil;
GameController *gameController = nil;
FlipsideViewController *flipSideController = nil; 


@implementation MainViewController

@synthesize containerView, mainView, flipToView, labelRound, labelPoints, timeBar;

//
//
//
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) 
	{
        // Custom initialization
    }
    return self;
}

//
//	
//
 - (void)viewDidLoad 
{
	[super viewDidLoad];
	 
	// init pointer with nil
	flipSideController = nil;
	cardArray = nil;
	positionArray = nil;
	
	// init accelerator
	filter = [[[HighpassFilter class] alloc] initWithSampleRate:sampleRate cutoffFrequency:cutoffFrequency from:self];
	[[UIAccelerometer sharedAccelerometer] setUpdateInterval: updateInterval];
	[[UIAccelerometer sharedAccelerometer] setDelegate:self];
	 
	// recreate game controller when user changes settings, e.g. when nr of cards will be changed
	gameController = [[GameController alloc] initWithParameters:optionsNrOfCards group:optionsCardsToCompare view:(id *)self timer:optionsSecondsToRun];
	 
	// init option values
	optionsSecondsToRun = 60;			// how long does one game run init for the first round is one minute
	 
	NSString *str = [NSString stringWithFormat:@"%d", gamePoints];
	//round = [NSString stringWithFormat:@"%d / %d",currentRoundNr,gamePoints];
	labelPoints.text = str;
	 
	// create cards
	[self createCards];
 }

#pragma mark-
#pragma mark AccelerometerFiler
// UIAccelerometerDelegate method, called when the device accelerates.
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
	// Update the accelerometer graph view
	[filter addAcceleration:acceleration];
}

//
// function to create def. number of cards, add them to an array and randomize the order
//
-(void)createCards
{	
	// delete all existing cards first (for game restart)
	if (cardArray != nil) 
	{
		for (int i=0; i<[cardArray count]; i++)
		{
			[((Card *)[cardArray objectAtIndex:i]) removeFromSuperview];
		}
		[cardArray removeAllObjects];
		[cardArray release];
		cardArray = nil;
	}
	
	// create new cards
	cardArray = [[NSMutableArray alloc] init];
	Card* card = nil;
	
	int group = 0;
	int groupCounter = optionsCardsToCompare;
	
	[self calculatePositions:optionsNrOfCards];
	
	// randomize positions array -> shake the cards
	NSUInteger firstObject = 0;	
	for (int i = 0; i<[positionArray count]; i++) 
	{
		NSUInteger randomIndex = random() % [positionArray count];
		[positionArray exchangeObjectAtIndex:firstObject withObjectAtIndex:randomIndex];
		firstObject +=1;
		
	}
	
	for (int i = 0; i < optionsNrOfCards; i++) 
	{
		MyPoint *p = [[positionArray objectAtIndex:0] retain];		
		[positionArray removeObjectAtIndex:0];
		
		// 2do: group muss noch gemacht werden, sollte nicht 0 sein
		card = [self createCardWithX:p.x Y:p.y Counter:i Group:group];
		[cardArray addObject:card];
		[p release];
		
		groupCounter--;
		if (groupCounter == 0) 
		{
			group++;
			groupCounter = optionsCardsToCompare;
		}
	}
	
	[positionArray release];
	positionArray = nil;
	timeBar.progress = 1.0;
	
}

//
// update the timer bar
//
-(void) updateTimerBar:(CGFloat) progress
{
	//NSLog(@"Bar: %f",progress);
	timeBar.progress = progress;
}

//
// message if time expired and game is not ready -> game over - time out
//
-(void) onTimer 
{
	//NSLog(@"Game over - time out");
	
	UIAlertView *gameOver = [[UIAlertView alloc] initWithTitle: @"Game over" message: @"You run out of time ..." delegate: self cancelButtonTitle: @"Start new game" otherButtonTitles: nil];
	[gameOver show];
	[gameOver release];
}

//
//	message for "Game solved within time"
//
-(void) onGameSolved:(int) seconds round:(int) roundNr
{
	currentRoundNr = roundNr;
	NSString *msg = nil;
	
	if (seconds == 0) 
	{
		msg = [NSString stringWithFormat:@"You solved the game. \n(no time limit)"];
	}
	else 
	{
		msg = [NSString stringWithFormat:@"You solved the game within \n %d seconds",seconds];		
	}

	
	UIAlertView *gameSolved = [[UIAlertView alloc] initWithTitle: @"Contratulation!" message: msg delegate: self cancelButtonTitle: @"Next round" otherButtonTitles: nil];
	[gameSolved show];
	[gameSolved release];
}

//
//	message for "start new Game if you shaked the phone"
//
-(void) onShake
{
	//NSLog(@"Shaked - start new game?");
	
	[gameController pauseTimer];
	
	UIAlertView *shaked = [[UIAlertView alloc] initWithTitle: @"Phone shaked!" message: @"Start new game?" delegate: self cancelButtonTitle: @"Yes" otherButtonTitles: @"No", nil];
	[shaked show];
	[shaked release];
}

//
//	alertView
//
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 
{
	
	if (buttonIndex == 0)
	{
		//NSLog(@"new game clicked");
		
		if([alertView.title isEqualToString:@"Phone shaked!"]) 
		{
			//NSLog(@"Phone shaked");
			[self startNewGameAndReset:YES];
		}
		else 
		{
			//NSLog(@"new round");
			[self startNewGameAndReset:NO];
		}

	} else if (buttonIndex == 1) 
	{
		//NSLog(@"button index 1 - no clicked");
		
		[gameController resumeTimer];
	}
}

//
//	start a new Game
//
-(void) startNewGameAndReset:(bool) reset
{
	// deletes old cards and creates new cards for new game
	[self createCards];

	NSString *round = nil;
	// On options changed or shaked -> reset the game
	if (reset)
	{
		round = [NSString stringWithFormat:@"0 /"];
		[gameController resetRounds];
				
		gamePoints = 0;
		[self addPoints:0];		
	}
	else 
	{
		round = [NSString stringWithFormat:@"%d /",currentRoundNr];
	}
	
	// actual round to label
	labelRound.text = round;
	
	// Set game controller to default values
	[gameController initParameters:optionsNrOfCards group:optionsCardsToCompare timer:optionsSecondsToRun];
	
}


//
// calculate the positions of the cards
//
-(void) calculatePositions:(int) nrOfCards
{
	positionArray = [[NSMutableArray alloc] init];
	
	int border = 12;
	int gap = 5;
	
	for (int j=0; j<rowMax; j++) 
	{
		for (int i=0; i<colMax; i++) 
		{
			
			MyPoint *p = [[MyPoint alloc] init];
			
			p.x = border+(cardWidth+gap)*j;
			p.y = border+(cardHeight+gap)*i;
			
			[positionArray addObject:p];
			[p release];
		}
	}
}

//
//	create one card at pos X/Y with a given ID
//
-(Card*)createCardWithX:(int)xPos Y:(int)yPos Counter:(int)counterID Group:(int)groupID
{
	frame = CGRectMake(xPos, yPos, cardWidth, cardHeight);
	
	NSString *pic;
	NSString *back;
	
	switch (optionsTypeOfCards) 
	{
		
		case 1:
			pic = [NSString stringWithFormat:@"%d_%d%@",optionsNrOfCards,(groupID+1),@"symbol.png"];
			back = [NSString stringWithFormat:@"%d_%@",optionsNrOfCards,@"backg.png"];
			break;
		case 2:
			pic = [NSString stringWithFormat:@"%d_%d%@",optionsNrOfCards,(groupID+1),@"picture.png"];
			back = [NSString stringWithFormat:@"%d_%@",optionsNrOfCards,@"backg.png"];
			break;
		default:
			pic = [NSString stringWithFormat:@"%d_%d%@",optionsNrOfCards,(groupID+1),@"number.png"];
			back = [NSString stringWithFormat:@"%d_%@",optionsNrOfCards,@"backg.png"];
			break;
	}
	
	
	NSLog(@"back: %@",back);
	
	Card *dragger = [[Card alloc] initWithFrame:frame 
									frontImage:[UIImage imageNamed:back] 
									backImage:[UIImage imageNamed:pic]
									gameCardID:counterID
									gameGroupID:groupID
					 ];
	dragger.delegate = self;
	[dragger setUserInteractionEnabled:YES]; 
	[self.view addSubview:dragger];
	[dragger release];
	
	return dragger;
}

//
// msg from card -> card flipped
//
- (void)cardFlipped:(Card *) card
{
	[gameController checkGroupFound];
}


//
//	question from card -> possible to flip?
//
-(BOOL)cardShouldFlip:(Card *)card
{
	return [gameController cardShouldFlip:card];
}

//
//	update GamePoints and label
//
-(void) addPoints:(int) points
{
	gamePoints += points;
	//NSString *str = [NSString stringWithFormat:@"points: %d", gamePoints];
	NSString *str = [NSString stringWithFormat:@"%d", gamePoints];
	labelPoints.text = str;
}




/*
 // Override to allow orientations other than the default portrait orientation.
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
 // Return YES for supported orientations
 return (interfaceOrientation == UIInterfaceOrientationPortrait);
 }
 */


//
//	return from options/info screen
//	update changed values and start a new game
//
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller {
    
	[self dismissModalViewControllerAnimated:YES];
	
	BOOL newGame = NO;
	
	if(optionsSecondsToRun != flipSideController.optionsSecondsToRun)
	{
		
		optionsSecondsToRun = flipSideController.optionsSecondsToRun;
		if(optionsSecondsToRun == 0)
		{
			optionsSecondsToRun = -1;
		}
		newGame = YES;
	}
	
	if(optionsNrOfCards != flipSideController.optionsNrOfCards)
	{
		optionsNrOfCards = flipSideController.optionsNrOfCards;
		
		switch (optionsNrOfCards) {
			case 16:
				cardHeight = 97;
				cardWidth = 70;
				
				rowMax = 4;
				colMax = 4;
				break;
			case 20:
				cardHeight = 75;
				cardWidth = 70;
				
				rowMax = 4;
				colMax = 5;
				break;
			case 12:
				cardHeight = 97;
				cardWidth = 96;
				
				rowMax = 3;
				colMax = 4;
				break;
			default:
				break;
		}
		
		
		newGame = YES;
	}
	if(optionsCardsToCompare != flipSideController.optionsCardsToCompare)
	{
		optionsCardsToCompare = flipSideController.optionsCardsToCompare;
		newGame = YES;
	}
	if(optionsTypeOfCards != flipSideController.optionsTypeOfCards)
	{
		optionsTypeOfCards = flipSideController.optionsTypeOfCards;
		newGame = YES;
	}
	
	if (newGame) 
	{	
		[self startNewGameAndReset:YES];
	}
	else 
	{
		[gameController resumeTimer];
	}

	 [[UIAccelerometer sharedAccelerometer] setDelegate:self];
	
	
}


//
//	show info/options screen
//
- (IBAction)showInfo {    
	
	[gameController pauseTimer];
	[[UIAccelerometer sharedAccelerometer] setDelegate:nil];
	
	if (flipSideController == nil) {
		flipSideController = [[FlipsideViewController alloc] initWithNibName:@"FlipsideView" bundle:nil];
	}
	flipSideController.delegate = self;
		
	flipSideController.optionsSecondsToRun = optionsSecondsToRun;
	flipSideController.optionsCardsToCompare = optionsCardsToCompare; 
	flipSideController.optionsNrOfCards = optionsNrOfCards;
	flipSideController.optionsTypeOfCards = optionsTypeOfCards;
	
	flipSideController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
	[self presentModalViewController:flipSideController animated:YES];
}



/*
 // Override to allow orientations other than the default portrait orientation.
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
 // Return YES for supported orientations
 return (interfaceOrientation == UIInterfaceOrientationPortrait);
 }
 */

//
//
//
- (void)didReceiveMemoryWarning 
{
	// Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
	
	// Release any cached data, images, etc that aren't in use.
}

//
//
//
- (void)viewDidUnload {
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
	self.flipToView = nil;
	self.mainView = nil;
}


- (void)dealloc 
{
	[positionArray release];
    [cardArray release];
	
	[flipSideController release];
	
    [super dealloc];
}


@end
